package com.zhehekeji.opsys.api.plugin.wechat.util;

import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zhehekeji.opsys.api.util.Md5Utils;

/**
 * @ClassName SignUtils
 * @Description TODO
 * @author chenweiliu chenwei.liu@163.com
 * @date 2017-12-21   下午4:31:22
 */
public class SignUtils {
	
	private static final Logger log = LoggerFactory.getLogger(SignUtils.class);
	
	public static void main(String[] args) throws Exception {
		String act_name = "看直播领红包活动";
		String client_ip = "183.131.20.247";
		String mch_billno = "1483400172201801221118413335";
		String mch_id = "1483400172";
		String nonce_str="26F2E3A9384F4EA594F7242EF9E20B9E";
		String re_openid = "ovhqYwvQNUdPGGOzM72ml3htjzzE";
		String remark = "看越多得越多，快来领！";
		String scene_id = "PRODUCT_2";
		String send_name = "杭州行云信息";
		int total_amount = 100;
		int total_num = 1;
		String wishing = "感谢您参加活动，祝您新春快乐！";
		String wxappid = "wx02ac6e10ee574f73";
		String key = "5d9df5dcff05ee277e82438f5621186e";
		String sign = redpackSign(nonce_str, mch_billno, mch_id, wxappid, send_name, re_openid, total_amount, total_num, wishing, client_ip, act_name, remark, scene_id, key);
		System.out.println(sign);
		
		String tmp ="act_name=看直播领红包活动&client_ip=183.131.20.247&mch_billno=1483400172201801221118413335&mch_id=1483400172&nonce_str=26F2E3A9384F4EA594F7242EF9E20B9E&re_openid=ovhqYwvQNUdPGGOzM72ml3htjzzE&remark=看越多得越多，快来领！&scene_id=PRODUCT_2&send_name=杭州行云信息&total_amount=100&total_num=1&wishing=感谢您参加活动，祝您新春快乐！&wxappid=wx02ac6e10ee574f73&key=5d9df5dcff05ee277e82438f5621186e";
		System.out.println(md5Sign(tmp));
		
		/*//验证加密算法
		String signSrc = "appid=wxd930ea5d5a258f4f&body=test&device_info=1000&mch_id=10000100&nonce_str=ibuaiVcKdpRxkhJA";
		String key = "192006250b4c09247ec02edce69f6a2d";
		signSrc = signSrc + "&key=" + key;
		//MD5签名方式，预期输出：9A0A8659F005D6984697E2CA0A9CF3B7
		String sign = md5Sign(signSrc);
		System.out.println(sign);
		
		//HMAC-SHA256签名，预期输出：6A9AE1657590FD6257D693A078E1C3E4BB6BA4DC30B23E0EE2496E54170DACD6
		sign = hmacSign(signSrc.getBytes(), key.getBytes());
		System.out.println(sign);*/
	}
	/**
	 * 生成调用微信普通红包接口签名
	 * @param nonceStr 随机字符串，不长于32位
	 * @param mchid	微信支付分配的商户号
	 * @param wxappid 微信分配的公众账号ID
	 * @param sendName 红包发送者名称
	 * @param reOpenid 接受红包的用户，用户在wxappid下的openid
	 * @param totalAmount 付款金额，单位分
	 * @param totalNum 红包发放总人数
	 * @param wishing 红包祝福语
	 * @param clientIp 调用接口的机器Ip地址
	 * @param actName 活动名称
	 * @param remark 备注信息
	 * @param sceneid 场景id
	 * @param key 加密密钥
	 * @return
	 */
	public static String redpackSign(String nonceStr, String mchBillno, String mchid, String wxappid, 
			String sendName, String reOpenid, int totalAmount, int totalNum, String wishing,
			String clientIp, String actName, String remark, String sceneid, String key){
		Map<String, Object> map = new HashMap<String, Object>();
		map.put("nonce_str", nonceStr);
		map.put("mch_billno", mchBillno);
		map.put("mch_id", mchid);
		map.put("wxappid", wxappid);
		map.put("send_name", sendName);
		map.put("re_openid", reOpenid);
		map.put("total_amount", totalAmount);
		map.put("total_num", totalNum);
		map.put("wishing", wishing);
		map.put("client_ip", clientIp);
		map.put("act_name", actName);
		map.put("remark", remark);
		if (!StringUtils.isBlank(sceneid)){
			map.put("scene_id", sceneid);
		}
		Set<String> set = map.keySet();
		String[] params = new String[set.size()];
		set.toArray(params);
		Arrays.sort(params);
		Object value;
		String param;
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < params.length; i ++){
			param = params[i];
			value = map.get(param);
			if (value == null){
				continue;
			}
			if (value instanceof String){
				if (((String)value).trim() == ""){
					continue;
				}
			}
			if (i == params.length - 1){
				sb.append(param).append("=").append(value);
			}else{
				sb.append(param).append("=").append(value).append("&");
			}
		}
		String signSrc = sb.toString() + "&key=" + key;
		return md5Sign(signSrc);
	}
	
	public static String md5Sign(String src){
		return Md5Utils.md5Encode(src);
	}
	
	public static String hmacSign(byte[] bsrc, byte[] bkey){
		if (bsrc == null || bsrc.length == 0){
			return null;
		}
		if (bkey == null || bkey.length == 0){
			return null;
		}
		SecretKeySpec signingKey = new SecretKeySpec(bkey, "HmacSHA256");
		Mac mac;
		try {
			mac = Mac.getInstance("HmacSHA256");
			mac.init(signingKey);
			return byteToHexString(mac.doFinal(bsrc));
		} catch (Exception e) {
			log.error(e.getMessage(), e);
		}
		return null;
	}
	
	public static String byteToHexString(byte[] src) {
	    StringBuilder sb = new StringBuilder();
	    String str;
	    for (int i = 0; src!=null && i < src.length; i++) {
	        str = Integer.toHexString(src[i] & 0XFF);
	        if (str.length() == 1){
	            sb.append('0');
	        }
	        sb.append(str);
	    }
	    return sb.toString().toUpperCase();
	}
}

